package org.duang.kit;

import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.duang.http.base.HttpClient;
import org.duang.http.base.HttpRes;
import org.duang.http.common.ResponseMessage;
import org.duang.http.core.enums.HttpMethod;
import org.duang.http.core.inter.AsyncCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * HttpClient 请求工具类
 * @author laotang
 */
public class HttpKit {
	
	private static Logger logger = LoggerFactory.getLogger(HttpKit.class);
	
	private static Map<String,Object> params;
	private static Map<String,File> files;
	private String url;
	private static boolean isSecurity;
	private static InputStream content;
	private static HttpKit httpKit;
	private static ContentTypeEnum contentTypeEnum;
	private static Map<String,String> headers;
	private static String filePath;
	
	//证书
	private static String certPathStr;
	private static String certPassStr;
	
	public final static String TOKENID_FIELD = "tokenid";
	
	public enum ContentTypeEnum{
		
		//注意不要有分号结尾
		JSON("application/json"),
		TEXT_HTML("application/x-www-form-urlencoded; text/html");
		
		private ContentTypeEnum( String value) {
			this.value = value;
		}
		private final String value;
		public String getValue() {
			return value;
		}
	}
	
	public static HttpKit duang(){
		if(ToolsKit.isEmpty(httpKit)){
			httpKit = new HttpKit();
		}
		if(ToolsKit.isEmpty(params)){
			params = new HashMap<String,Object>();
		}
		if(ToolsKit.isEmpty(files)){
			files = new HashMap<String,File>();
		}
		if(ToolsKit.isEmpty(headers)){
			headers = new HashMap<String,String>();
		} 
		colse();
		return httpKit;
	}
	
	/**
	 * 清理各种变量
	 */
	private static void colse() {
		if(ToolsKit.isNotEmpty(content)){
			try {
				content.close();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				content = null;
			}
		}		
		params.clear();
		headers.clear();
		files.clear();
		isSecurity = false;
		contentTypeEnum = null;
		certPathStr = null;
		certPassStr = null;
		filePath = null;
	}
	
	public HttpKit setTokenId(String value) {
		params.put(TOKENID_FIELD, value);
		return this;
	}
	
	
	public HttpKit param(String key, Object value) {
		if(value instanceof java.io.File){
			throw new IllegalArgumentException("参数里包含有文件属性，请使用files方法上传文件 !");
		}
		if(!key.equalsIgnoreCase(TOKENID_FIELD)){
			params.put(key, value);
		}
		return this;
	}
	
	public HttpKit param(Map<String,Object> paramMap) {
		params.putAll(paramMap);
		params.remove(TOKENID_FIELD);
		return this;
	}
	
	public HttpKit file(String key, File value) {
		if(params.size() > 0){
			throw new IllegalArgumentException("params不为空，不能与params方法同时使用！");
		}
		files.put(key, value);
		return this;
	}
	
	public HttpKit body(String value) {
		if(ToolsKit.isNotEmpty(value))
			content = ToolsKit.string2InputStream(value, ToolsKit.CHARSET_UTF_8);
		return this;
	}
	
	public HttpKit body(InputStream value) {
		if(ToolsKit.isNotEmpty(value)) content = value;
		return this;
	}
	
	public HttpKit header(Map<String,String> headerMap) {
		headers.putAll(headerMap);
		return this;
	}
	
	public HttpKit type(ContentTypeEnum enums) {
		contentTypeEnum = enums;
		return this;
	}
	
	public HttpKit url(String url) {
		this.url = url;
		return this;
	}
	
	public HttpKit security(boolean security) {
		isSecurity = security;
		return this;
	}
	
	 public HttpKit saveas(String saveas) {
		File file = new File(saveas);
		saveas = file.getAbsolutePath().toString();
		if( saveas.indexOf(".") == -1 ) {
			throw new IllegalArgumentException("文件路径有误，请输入一个文件的绝对路径，包括文件名！");
		}
        filePath = saveas;
        return this;
    }
	
	/**
	 * 证书
	 * @param certPath		证书路径
	 * @param certPass			证书密码
	 * @return
	 */
	public HttpKit SSL(String certPath, String certPass) {
		certPathStr = certPath;
		certPassStr = certPass;
		return this;
	}
	
	public HttpRes get() {
		return request(HttpMethod.GET, null);
	}
	
	public HttpRes post() {
		return request(HttpMethod.POST, null);
	}
	
	public HttpRes put() {
		return request(HttpMethod.PUT, null);
	}
	
	public HttpRes delete() {
		return request(HttpMethod.DELETE, null);
	}
	
	public HttpRes head() {
		return request(HttpMethod.HEAD, null);
	}
	public HttpRes options() {
		return request(HttpMethod.OPTIONS, null);
	}
	
	public HttpRes upload() {
		return request(HttpMethod.POST, null);
	}
	
	public HttpRes shorturl() {
		return request(HttpMethod.POST, null);
	}
	
	public void get(AsyncCallback<ResponseMessage> callback) {
		request(HttpMethod.GET, callback);
	}
	
	public void post(AsyncCallback<ResponseMessage> callback) {
		request(HttpMethod.POST, callback);
	}
	
	public HttpRes request(HttpMethod method, AsyncCallback<ResponseMessage> callback) {
		try{			
			boolean isNotSSL =  ToolsKit.isEmpty(certPathStr) && ToolsKit.isEmpty(certPassStr);
			if(isNotSSL){
				
//				 Content content2 = Request.Post(url).bodyString(content.toString(), ContentType.APPLICATION_JSON).execute().returnContent();
//				 HttpRes res = new HttpRes();
//				 res.setStatusCode(200);
//				 res.setResult("2000");
//				 return res;
				if(files.size() > 0) {
					HttpClient client = new HttpClient(method, url, headers, files);
					return client.upload();
				} else {
					HttpClient client = new HttpClient(method, url, params, content, headers);
					client.setSecurity(isSecurity);
					client.setContentType(contentTypeEnum);
					if(ToolsKit.isEmpty(callback)){
						return client.send();
					} else {
						client.send(callback);
					}
				}
			} else {
				HttpClient client = new HttpClient(url, content, headers, certPathStr, certPassStr);
				return client.sendSSL();
			}
		} catch ( Exception e ){
			e.printStackTrace();
			logger.warn(e.getMessage(), e);
		} finally{
			colse();
		}
		return null;
	}
	
	public File download() {
	    if(ToolsKit.isEmpty(filePath)) {
	        String rootPath = PathKit.getWebRootPath();
	        String fileName = url.substring(url.lastIndexOf("/")+1, url.length());
	        String extName = fileName.substring(fileName.lastIndexOf(".")+1, fileName.length());
	        filePath = rootPath + "/downloadfiles/"+extName+"/"+ ToolsKit.getCurrentDate("yyyyMMdd")+"/"+fileName;
	    }
	    HttpClient client = new HttpClient(HttpMethod.GET, url, null, null, headers);
	    try{
	        return client.download(filePath);
	    } catch(Exception e){
	        e.printStackTrace();
	        logger.warn(e.getMessage(), e);
	    } finally{
	        colse();
	    }
	    return null;
	}
}
